package com.luo.d3s.core.util;

import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;

/**
 * Optional工具
 *
 * @author luohq
 * @date 2023-01-06 11:22
 */
public class Optionals {

    /**
     * 根据initValue执行转换逻辑，若其中任一转换返回空则返回空，否则返回转换后的结果
     *
     * @param initValue 初始值
     * @param mapFunc   转换函数
     * @return 转换结果（默认null）
     * @param <T> 初始值类型
     * @param <R> 转换后类型
     */
    public static <T, R> R defaultNull(T initValue, Function<T, R> mapFunc) {
        return Optional.ofNullable(initValue)
                .map(mapFunc)
                .orElse(null);
    }

    /**
     * 根据initValue执行转换逻辑，若其中任一转换返回空则返回空，否则返回转换后的结果
     *
     * @param initValue 初始值
     * @param mapFunc1  转换函数1
     * @param mapFunc2  转换函数2
     * @return 转换结果（默认null）
     * @param <T>  初始值类型
     * @param <R1> 中间转换后类型1
     * @param <R2> 转换后类型2（最终结果类型）
     */
    public static <T, R1, R2> R2 defaultNull(T initValue, Function<T, R1> mapFunc1, Function<R1, R2> mapFunc2) {
        return Optional.ofNullable(initValue)
                .map(mapFunc1)
                .map(mapFunc2)
                .orElse(null);
    }

    /**
     * 根据initValue执行转换逻辑，若其中任一转换返回空则返回空，否则返回转换后的结果
     *
     * @param initValue 初始值
     * @param mapFunc1  转换函数1
     * @param mapFunc2  转换函数2
     * @param mapFunc3  转换函数3
     * @return 转换结果（默认null）
     * @param <T>  初始值类型
     * @param <R1> 中间转换后类型1
     * @param <R2> 中间转换后类型2
     * @param <R3> 转换后类型3（最终结果类型）
     */
    public static <T, R1, R2, R3> R3 defaultNull(T initValue, Function<T, R1> mapFunc1, Function<R1, R2> mapFunc2, Function<R2, R3> mapFunc3) {
        return Optional.ofNullable(initValue)
                .map(mapFunc1)
                .map(mapFunc2)
                .map(mapFunc3)
                .orElse(null);
    }

    /**
     * 根据initValue执行转换逻辑并判断转换后结果是否为空
     *
     * @param initValue 初始值
     * @param mapFunc   转换函数
     * @return 转换后结果是否为空
     * @param <T> 初始值类型
     * @param <R> 转换后类型
     */
    public static <T, R> Boolean isNull(T initValue, Function<T, R> mapFunc) {
        return Objects.isNull(defaultNull(initValue, mapFunc));
    }

    /**
     * 根据initValue执行转换逻辑并判断转换后结果是否为空
     *
     * @param initValue 初始值
     * @param mapFunc1  转换函数1
     * @param mapFunc2  转换函数2
     * @return 转换后结果是否为空
     * @param <T>  初始值类型
     * @param <R1> 中间转换后类型1
     * @param <R2> 转换后类型2（最终结果类型）
     */
    public static <T, R1, R2> Boolean isNull(T initValue, Function<T, R1> mapFunc1, Function<R1, R2> mapFunc2) {
        return Objects.isNull(defaultNull(initValue, mapFunc1, mapFunc2));
    }

    /**
     * 根据initValue执行转换逻辑并判断转换后结果是否为空
     *
     * @param initValue 初始值
     * @param mapFunc1  转换函数1
     * @param mapFunc2  转换函数2
     * @param mapFunc3  转换函数3
     * @return 转换后结果是否为空
     * @param <T>  初始值类型
     * @param <R1> 中间转换后类型1
     * @param <R2> 中间转换后类型2
     * @param <R3> 转换后类型3（最终结果类型）
     */
    public static <T, R1, R2, R3> Boolean isNull(T initValue, Function<T, R1> mapFunc1, Function<R1, R2> mapFunc2, Function<R2, R3> mapFunc3) {
        return Objects.isNull(defaultNull(initValue, mapFunc1, mapFunc2, mapFunc3));
    }


}
